/*
 * Copyright (c) 2011 Ball State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * NOTE:
 * Derivative work based on the Google IO 2011 Schedule app released for open source
 * http://code.google.com/p/iosched/
 */

package edu.bsu.android.gtv.apps.bconnected.ui;

import java.io.IOException;
import java.util.ArrayList; 

import edu.bsu.android.gtv.apps.bconnected.R;
import edu.bsu.android.gtv.apps.bconnected.data.DegreeData;
import edu.bsu.android.gtv.apps.bconnected.data.PersonData;
import edu.bsu.android.gtv.apps.bconnected.objects.Degree;
import edu.bsu.android.gtv.apps.bconnected.objects.Person;
import edu.bsu.android.gtv.apps.bconnected.ui.base.BaseActivity;
import edu.bsu.android.gtv.apps.bconnected.util.AnalyticsUtils;
import edu.bsu.android.gtv.apps.bconnected.util.Constants;
import edu.bsu.android.gtv.apps.bconnected.util.Crypto;
import edu.bsu.android.gtv.apps.bconnected.util.DisclaimerHelper;
import edu.bsu.android.gtv.apps.bconnected.util.LoginHelper;
import edu.bsu.android.gtv.apps.bconnected.util.UIUtils;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;

/**
 * An activity that shows detail information for a the student - including advisor and degree information. Single pane activity containing 
 * tabs for the advisor and degree.
 * @author Kyle Parker, University Computing Services
 */
public class AboutMeActivity extends BaseActivity {
    private static final String TAG = "AboutMeFragment";
    private static final String TAG_ADVISOR = "advisor";
    private static final String TAG_DEGREE = "degree";

    private TabHost mTabHost;
    private Person mPerson;
    private View mLoadingSpinner;
    private View mAdvisorSpinner;
    private View mDegreeSpinner;
    private Activity mActivity;
    private BroadcastReceiver mReceiver;
    
    private String mLoginGuid;
    private String mBSUID;
    private boolean mLogin;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_about_me);
		
        getActivityHelper().setupActionBar(false);        
        mActivity = this;
        
        handleLogout();    
        handleLogin();
        
    	if (!DisclaimerHelper.hasAcceptedDisclaimer(mActivity)) {
    		DisclaimerHelper.showDisclaimer(false, mActivity);
    	}
                
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
       	mTabHost.setup();

        mLoadingSpinner = findViewById(R.id.loading_spinner); 
        mLoadingSpinner.setVisibility(View.VISIBLE); 

        mAdvisorSpinner = findViewById(R.id.spinner_advisor); 
        mAdvisorSpinner.setVisibility(View.VISIBLE);

        mDegreeSpinner = findViewById(R.id.spinner_degree); 
        mDegreeSpinner.setVisibility(View.VISIBLE);

        setupAdvisorTab();
        setupDegreeTab();

		// Hide the personal information while the data is loading
		hideAboutMe();		
        if (mLogin) {
			loadAboutMe();
        }

		// Set the current tab to the last selection of the student - either the advisor or the degree
        mTabHost.setCurrentTab(UIUtils.getLastID(mActivity, Constants.PREF_ABOUT_ME_TAB));
        // Reset the tab position
        UIUtils.setLastID(mActivity, Constants.PREF_ABOUT_ME_TAB, 0);

        AnalyticsUtils.getInstance(mActivity).trackPageView("/AboutMe");
        UIUtils.setTitle(mActivity, "About Me");
    }
    
    @Override 
    public void onDestroy() {
    	super.onResume();
    	mActivity.unregisterReceiver(mReceiver);
    }

    /**
     * Using a new thread, separate from the main activity, load the personal information from the service handler
     */
    private void loadAboutMe() {		
        Runnable load = new Runnable(){
            public void run() {
            	try {
	            	PersonData.initializePerson(mBSUID, Constants.QUERY_PERSON_DIRECTORY_STUDENT, mActivity);
	            	
	            	if (PersonData.getPersonCount() > 0) {
	            		mPerson = PersonData.getPerson(0);
	            	}
	    	    	
	    	    	mActivity.runOnUiThread(returnPerson);
            	} catch (Exception ex) {        
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadAboutMe");
        thread.start();
    }

    /**
     * Load the personal info from the service handler and set the visibility of the spinner to "gone"
     */
    private Runnable returnPerson = new Runnable(){
        public void run() {
        	displayAboutMe();
        	
            mLoadingSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the advisor from the service handler
     */
    private void loadAdvisor() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
                	PersonData.initializeAdvisor(mBSUID, mLoginGuid, mActivity);
        	    	
            		mActivity.runOnUiThread(returnAdvisor);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadAdvisor");
        thread.start();
    }
    
    /**
     * Display the advisors in a separate thread
     */
    private Runnable returnAdvisor = new Runnable(){
        public void run() {
        	// If the call to the advisor service did not return the "error" attribute, then display the advisors, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (PersonData.getAdvisorAuth()) {
            	displayAdvisor();
            	
                if (PersonData.getAdvisorCount() == 0) {
                    TextView empty = ((TextView) findViewById(R.id.empty_advisor));
                    empty.setVisibility(View.VISIBLE);
                }
        	}

            mAdvisorSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the degree from the service handler
     */
    private void loadDegree() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
                	DegreeData.initializeDegree(mBSUID, mLoginGuid, mActivity);
        	    	
            		mActivity.runOnUiThread(returnDegree);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadDegree");
        thread.start();
    }
    
    /**
     * Display the degrees in a separate thread
     */
    private Runnable returnDegree = new Runnable(){
        public void run() {
        	// If the call to the degree service did not return the "error" attribute, then display the degrees, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (DegreeData.getDegreeAuth()) {
            	displayDegree();
            	
                if (DegreeData.getDegreeCount() == 0) {
                    TextView empty = ((TextView) findViewById(R.id.empty_degree));
                    empty.setVisibility(View.VISIBLE);
                }
        	} 

            mDegreeSpinner.setVisibility(View.GONE);
        }
    };
    
    /**
     * Display the personal information and show the advisor and degree
     */
    private void displayAboutMe() { 
    	if (mPerson != null) {
    		Crypto c = new Crypto(Constants.KEY);

    		LinearLayout view = (LinearLayout) findViewById(R.id.about_me_container);
            view.setVisibility(View.VISIBLE);
        	view.setBackgroundResource(R.color.content_background);
	    	
	    	loadAdvisor();
	    	loadDegree();

			UIUtils.displayTextView(view, R.id.name, (mPerson.getFirstName() + " " + mPerson.getMiddleName()).trim() + " " + 
					(mPerson.getLastName() + " " + mPerson.getNameSuffix()).trim());			
			try {
				String bsuID = c.decryptAsBase64(mPerson.getBSUID().getBytes());
				
				if (bsuID.length() == 9) {
					bsuID = bsuID.substring(0, 3) + "-" + bsuID.substring(3,6) + "-" + bsuID.substring(6,9);

					UIUtils.displayTextView(view, R.id.bsuid, mActivity.getString(R.string.content_bsu_id) + " " + bsuID);
				}
			} catch (IOException e) {
				UIUtils.displayTextView(view, R.id.bsuid, "");
			}	
			
			UIUtils.displayTextView(view, R.id.address, UIUtils.formatAddress(mPerson.getAddress1(), mPerson.getAddress2(), mPerson.getCity(), 
    				mPerson.getState(), mPerson.getZip()));
    		UIUtils.displayTextView(view, R.id.email, mPerson.getEmailAddress());
    		UIUtils.displayTextView(view, R.id.phone, mPerson.getPhone());
    		UIUtils.displayTextView(view, R.id.privacy_restriction, mActivity.getString(R.string.content_privacy_restriction) + " " + 
    				mPerson.getPrivacyRestriction());
    	} else {
    		hideAboutMe();
    		
    		findViewById(R.id.empty_about_me_container).setVisibility(View.VISIBLE);
            ((TextView) findViewById(R.id.empty_about_me)).setText(R.string.empty_about_me);
    	}
    }

    /**
     * Hide the about me view during the load process or if the person object is empty
     */
    private void hideAboutMe() {  
    	LinearLayout view = (LinearLayout) findViewById(R.id.about_me_container);
        view.setVisibility(View.GONE);			
        view.setBackgroundResource(R.drawable.empty_people_background);
    }
    
    /**
     * Display the advisor for the student
     */
    private void displayAdvisor() { 
    	if (PersonData.getAdvisorCount() > 0) {
            AdvisorAdapter adapter = new AdvisorAdapter(mActivity, PersonData.getAdvisors());
            
            final ListView lv = ((ListView) findViewById(R.id.advisors));
            lv.setAdapter(adapter); 
    	}
    }

    /**
     * AdvisorAdapter used to populate the listview for the advisor
     */
    private class AdvisorAdapter extends ArrayAdapter<Person> {
        private ArrayList<Person> items;
        
        public AdvisorAdapter(Context context, ArrayList<Person> items) {
            super(context, 0, items);
            this.items = items;
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent)  {        	
            View view = convertView;
            
            if (view == null) {
            	view = LayoutInflater.from(mActivity).inflate(R.layout.list_item_advisor, null);
            }
            
            Person advisor = items.get(position);   
             
            if (advisor != null) {
            	UIUtils.displayTextView(view, R.id.name, advisor.getAdvisorName());
            	UIUtils.displayTextView(view, R.id.type, advisor.getAdvisorType() + " " + mActivity.getString(R.string.content_advisor_type));
            	UIUtils.displayTextView(view, R.id.advising_center, advisor.getAdvisingCenter());
            	UIUtils.displayTextView(view, R.id.office, advisor.getOffice());
            	UIUtils.displayTextView(view, R.id.phone, advisor.getPhone());
            }
             
            return view;
        }
    }
    
    /**
     * Display the degree for the student
     */
    private void displayDegree() { 
    	if (PersonData.getAdvisorCount() > 0) {
            DegreeAdapter adapter = new DegreeAdapter(mActivity, DegreeData.getDegrees());
            
            final ListView lv = ((ListView) findViewById(R.id.degrees));
            lv.setAdapter(adapter); 
    	}
    }

    /**
     * DegreeAdapter used to populate the listview for the degrees
     */
    private class DegreeAdapter extends ArrayAdapter<Degree> {
        private ArrayList<Degree> items;
        
        public DegreeAdapter(Context context, ArrayList<Degree> items) {
            super(context, 0, items);
            this.items = items;
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent)  {        	
            View view = convertView;
            
            if (view == null) {
            	view = LayoutInflater.from(mActivity).inflate(R.layout.list_item_degree, null);
            }
            
            Degree degree = items.get(position);  
             
            if (degree != null) {
            	UIUtils.displayTextView(view, R.id.degree, degree.getDegreeType());
            	UIUtils.displayTextView(view, R.id.program, degree.getProgramOption());
            	UIUtils.displayTextView(view, R.id.program_type, degree.getProgramType());
            	UIUtils.displayTextView(view, R.id.department, degree.getDepartment());
            }
             
            return view;
        }
    }
    
    /**
     * Build and add "advisor" tab.
     */
    private void setupAdvisorTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_ADVISOR)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_advisors, mActivity))
                .setContent(R.id.tab_advisor));
    }
    
    /**
     * Build and add "degrees" tab.
     */
    private void setupDegreeTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_DEGREE)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_degrees, mActivity))
                .setContent(R.id.tab_degree));
    }

    /**
     * In order to protect the activity from the back stack after a student logs out, remove the activity 
     * If the student hits the back button, this will take them to the Home activity
     */
    private void handleLogout() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.ACTION_LOGOUT);
        mReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
		        intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
		        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_LOGOUT));
		        
		        mActivity.startActivity(intent); 
			    mActivity.finish();
			}
		};
		
        mActivity.registerReceiver(mReceiver, intentFilter);
    }
    
    /**
     * Determine if the person has logged in and whether there is a person object in the database
     * Get the student's BSU ID for use throughout the application
     */
    private void handleLogin() {
    	Person person = LoginHelper.checkLogin(mActivity);
    	
    	if (person != null) {
    		mBSUID = person.getBSUID();
        	mLoginGuid = person.getLoginGuid();
        	
        	mLogin = true;
    	} else {
	        Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
	        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_NOT_LOGGED_IN));
	        
	        mActivity.startActivity(intent); 
		    mActivity.finish();
		    
		    mLogin = false;
    	}  
    }
}
